package com.ruoyi.framework.config;

import com.alibaba.fastjson.JSON;
import com.ruoyi.system.domain.Article;
import com.ruoyi.system.mapper.ArticleMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: fulin
 * @Date: 2023/01/06/11:28
 * @Description:
 */
@ServerEndpoint("/article/{articleId}/{userId}")
@Component
public class ArticleSocketServer {

    /**
     * 存放文章集合 key为文章id value 为map
     * value集合 以用户id为key value为ArticleSocketServer对象
     */
    public static ConcurrentHashMap<String, ConcurrentHashMap<String, ArticleSocketServer>> articleMap = new ConcurrentHashMap<>();


    /**
     * 因为无法注入bean对象 所以通过ApplicationContext获取bean
     * @return
     */
    private ArticleMapper getArticleMapper() {
        return SpringContextUtil.getBean(ArticleMapper.class);
    }

    /**
     * 会话session
     */
    private Session session;

    /**
     * 用户id
     */
    private String userId;

    @OnOpen
    public void onOpen(Session session, @PathParam("articleId") String articleId, @PathParam("userId") String userId) throws IOException {
        this.session = session;
        this.userId = userId;
        //协助的用户
        if (articleMap.containsKey(articleId)) {
            articleMap.get(articleId).put(userId, this);
        } else {
            //第一个进入用户
            ConcurrentHashMap<String, ArticleSocketServer> articleServer = new ConcurrentHashMap<>();
            articleServer.put(userId, this);
            articleMap.put(articleId, articleServer);
        }
        init(articleId, userId);
    }

    /**
     * 初始化读取文章内容
     * @param articleId
     * @param userId
     */
    public void init(String articleId, String userId) {
        Article article = getArticleMapper().findById(articleId);
        sendMessageFirst(article, userId);
    }

    public void sendMessage(Article article, String userId) {
        //获取socket集合
        if (Objects.isNull(article) || Objects.isNull(articleMap.get(article.getId()))) return;
        ConcurrentHashMap<String, ArticleSocketServer> socketServerConcurrentHashMap = articleMap.get(article.getId());
        //获取用户id集合
        List<String> userLists = new ArrayList<>();
        socketServerConcurrentHashMap.forEach((k, v) -> {
            userLists.add(k);
        });
        //封装消息->加入用户信息集合
        article.setUserIds(userLists);
        String message = JSON.toJSONString(article);
        //发送信息
        socketServerConcurrentHashMap.forEach((k, v) -> {
            try {
                if (!k.equals(userId)) {
                    v.session.getAsyncRemote().sendText(message);
                }
            } catch (Exception e) {
                e.printStackTrace();
                //移除不活跃用户
                destroy(article.getId(), userId);
            }
        });
    }


    /**
     * 第一次链接
     * 给所有用户发文章内容
     * 用户更新在线用户
     * @param article
     * @param userId
     */
    public void sendMessageFirst(Article article, String userId) {
        //获取socket集合
        if (Objects.isNull(article) || Objects.isNull(articleMap.get(article.getId()))) return;
        ConcurrentHashMap<String, ArticleSocketServer> socketServerConcurrentHashMap = articleMap.get(article.getId());
        //获取用户id
        List<String> userLists = new ArrayList<>();
        socketServerConcurrentHashMap.forEach((k, v) -> {
            userLists.add(k);
        });
        //封装消息->加入用户信息集合
        article.setUserIds(userLists);
        String message = JSON.toJSONString(article);
        //发送信息
        socketServerConcurrentHashMap.forEach((k, v) -> {
            try {
                v.session.getAsyncRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
                //移除不活跃用户
                destroy(article.getId(), userId);
            }
        });
    }

    /**
     * 删除集合中 不活跃的session
     * @param articleId
     * @param userId
     */
    public void destroy(String articleId, String userId) {
        articleMap.get(articleId).remove(userId);
    }

    @OnMessage
    public void onMessage(String message, Session session) {

    }

    @OnClose
    public void onClose(Session session, @PathParam("articleId") String articleId, @PathParam("userId") String userId) {
        destroy(articleId, userId);
    }
}
